home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / SPELL.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  12KB  |  487 lines

  1. /*    SCCS Id: @(#)spell.c    3.0    88/09/18
  2.  *
  3.  *    Copyright (c) M. Stephenson 1988
  4.  */
  5. /* NetHack may be freely redistributed.  See license for details. */
  6.  
  7. #include "hack.h"
  8. #ifdef SPELLS
  9. static schar NEARDATA delay;        /* moves left for this spell */
  10. static struct obj NEARDATA *book;    /* last/current book being xscribed */
  11.  
  12. #ifdef HARD
  13. #define spelluses(spell)    spl_book[spell-1].sp_uses
  14. #define decrnuses(spell)    spl_book[spell-1].sp_uses--
  15. #endif /* HARD */
  16. #define spellev(spell)        spl_book[spell-1].sp_lev
  17. #define spellname(spell)    objects[spl_book[spell-1].sp_id].oc_name
  18. #define spellid(spell)        spl_book[spell-1].sp_id
  19.  
  20. static void FDECL(cursed_book, (int));
  21. STATIC_PTR int NDECL(learn);
  22. static int NDECL(getspell);
  23. static char FDECL(spellet, (int));
  24.  
  25. static void
  26. cursed_book(lev)
  27.     register int    lev;
  28. {
  29.     switch(rn2(lev)) {
  30.     case 0:
  31.         You("feel a wrenching sensation.");
  32.         tele();        /* teleport him */
  33.         break;
  34.     case 1:
  35.         You("feel threatened.");
  36.         aggravate();
  37.         break;
  38.     case 2:
  39.         make_blinded(Blinded + rn1(100,250),TRUE);
  40.         break;
  41.     case 3:
  42.         take_gold();
  43.         break;
  44.     case 4:
  45.         pline("These runes were just too much to comprehend.");
  46.         make_confused(HConfusion + rn1(7,16),FALSE);
  47.         break;
  48.     case 5:
  49.         pline("The book was coated with contact poison!");
  50.         if (uarmg) {
  51.             if (uarmg->rustfree)
  52.             Your("gloves seem unaffected.");
  53.             else if (uarmg->spe > -2) {
  54.             Your("gloves corrode!");
  55.             uarmg->spe--;
  56.             } else
  57.             Your("gloves %s quite corroded.",Blind ? "feel":"look");
  58.             break;
  59.         }
  60.         if(Poison_resistance) {
  61.             losestr(rn1(1,2));
  62.             losehp(rnd(6), "contact-poisoned spellbook", KILLED_BY_AN);
  63.         } else {
  64.             losestr(rn1(4,3));
  65.             losehp(rnd(10), "contact-poisoned spellbook", KILLED_BY_AN);
  66.         }
  67.         break;
  68.     case 6:
  69.         if(Antimagic) {
  70.             shieldeff(u.ux, u.uy);
  71.             pline("The book explodes, but you are unharmed!");
  72.         } else {
  73.             pline("As you read the book, it explodes in your %s!",
  74.             body_part(FACE));
  75.             losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN);
  76.         }
  77.         break;
  78.     default:
  79.         rndcurse();
  80.         break;
  81.     }
  82.     return;
  83. }
  84.  
  85. STATIC_PTR
  86. int
  87. learn()
  88. {
  89.     register int    i;
  90.     register unsigned booktype;
  91.  
  92.     if (delay) {    /* not if (delay++), so at end delay == 0 */
  93.         delay++;
  94.         return(1); /* still busy */
  95.     }
  96.  
  97.     booktype = book->otyp;
  98.     for (i = 0; i < MAXSPELL; i++)  {
  99.         if (spl_book[i].sp_id == booktype)  {
  100. #ifdef HARD
  101.             Your("knowledge of that spell is keener.");
  102.             spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev);
  103. #else
  104.             pline("Oh, you already know that one!");
  105. #endif
  106.             break;
  107.         } else if (spl_book[i].sp_id == NO_SPELL)  {
  108.             spl_book[i].sp_id = booktype;
  109.             spl_book[i].sp_lev = objects[booktype].spl_lev;
  110.             spl_book[i].sp_flags = objects[booktype].bits;
  111. #ifdef HARD
  112.             /* spells have 2 .. 10-level uses. */
  113.             /* ie 2 or 3 uses w/ most potent */
  114.             spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev);
  115. #endif
  116.             You("add the spell to your repertoire.");
  117.             makeknown(booktype);
  118.             break;
  119.         }
  120.     }
  121.     if (i == MAXSPELL) impossible("Too many spells memorized!");
  122.  
  123.     if (book->cursed) {    /* maybe a demon cursed it */
  124.         cursed_book(objects[booktype].spl_lev);
  125.     }
  126.  
  127.     useup(book);
  128.     book = 0;
  129.     return(0);
  130. }
  131.  
  132. int
  133. study_book(spellbook)
  134. register struct obj *spellbook;
  135. {
  136.     register int     booktype = spellbook->otyp;
  137.  
  138.     if (delay && spellbook == book)
  139.         You("continue your efforts to memorize the spell.");
  140.     else {
  141.         switch(booktype)  {
  142.  
  143. /* level 1 spells */
  144.     case SPE_HEALING:
  145.     case SPE_DETECT_MONSTERS:
  146.     case SPE_FORCE_BOLT:
  147.     case SPE_LIGHT:
  148.     case SPE_SLEEP:
  149.     case SPE_KNOCK:
  150. /* level 2 spells */
  151.     case SPE_MAGIC_MISSILE:
  152.     case SPE_CONFUSE_MONSTER:
  153.     case SPE_SLOW_MONSTER:
  154.     case SPE_CURE_BLINDNESS:
  155.     case SPE_CREATE_MONSTER:
  156.     case SPE_DETECT_FOOD:
  157.     case SPE_WIZARD_LOCK:
  158.         delay = -objects[booktype].oc_delay;
  159.         break;
  160. /* level 3 spells */
  161.     case SPE_HASTE_SELF:
  162.     case SPE_CAUSE_FEAR:
  163.     case SPE_CURE_SICKNESS:
  164.     case SPE_DETECT_UNSEEN:
  165.     case SPE_EXTRA_HEALING:
  166.     case SPE_CHARM_MONSTER:
  167.     case SPE_CLAIRVOYANCE:
  168. /* level 4 spells */
  169.     case SPE_LEVITATION:
  170.     case SPE_RESTORE_ABILITY:
  171.     case SPE_INVISIBILITY:
  172.     case SPE_FIREBALL:
  173.     case SPE_DETECT_TREASURE:
  174.         delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay;
  175.         break;
  176. /* level 5 spells */
  177.     case SPE_REMOVE_CURSE:
  178.     case SPE_MAGIC_MAPPING:
  179.     case SPE_CONE_OF_COLD:
  180.     case SPE_IDENTIFY:
  181.     case SPE_DIG:
  182. /* level 6 spells */
  183.     case SPE_TURN_UNDEAD:
  184.     case SPE_POLYMORPH:
  185.     case SPE_CREATE_FAMILIAR:
  186.     case SPE_TELEPORT_AWAY:
  187.         delay = -objects[booktype].spl_lev * objects[booktype].oc_delay;
  188.         break;
  189. /* level 7 spells */
  190.     case SPE_CANCELLATION:
  191.     case SPE_FINGER_OF_DEATH:
  192.     case SPE_GENOCIDE:
  193.         delay = -8 * objects[booktype].oc_delay;
  194.         break;
  195. /* impossible */
  196.     default:
  197.         impossible("Unknown spellbook, %d;", booktype);
  198.         return(0);
  199.     }
  200.  
  201.         if(!spellbook->blessed &&
  202.             (spellbook->cursed ||
  203.                 rn2(20) > (ACURR(A_INT) + 4 + (int)(u.ulevel/2)
  204.                     - 2*objects[booktype].spl_lev))) {
  205.             cursed_book(objects[booktype].spl_lev);
  206.             nomul(delay);            /* study time */
  207.             delay = 0;
  208.             useup(spellbook);
  209.             return(1);
  210.         }
  211.  
  212.         You("begin to memorize the runes.");
  213.     }
  214.  
  215.     book = spellbook;
  216.     set_occupation(learn, "studying", 0);
  217.     return(1);
  218. }
  219.  
  220. static int
  221. getspell()  {
  222.  
  223.     register int    maxs, ilet, i;
  224.     char     lets[BUFSZ], buf[BUFSZ];
  225.  
  226.     if (spl_book[0].sp_id == NO_SPELL)  {
  227.  
  228.         You("don't know any spells right now.");
  229.         return(0);
  230.     } else  {
  231.  
  232.         for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
  233.         if (maxs >= MAXSPELL)  {
  234.  
  235.         impossible("Too many spells memorized.");
  236.         return(0);
  237.         }
  238.  
  239.         for(i = 0; (i < maxs) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;
  240.         for(i = 26; (i < maxs) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
  241.  
  242.         if (maxs == 1)  Strcpy(lets, "a");
  243.         else if (maxs < 27)  Sprintf(lets, "a-%c", 'a' + maxs - 1);
  244.         else if (maxs == 27)  Sprintf(lets, "a-z A");
  245.         else Sprintf(lets, "a-z A-%c", 'A' + maxs - 27);
  246.         for(;;)  {
  247.  
  248.         pline("Cast which spell? [%s ?] ", lets);
  249.         if ((ilet = readchar()) == '?')  {
  250.             (void) dovspell();
  251.             continue;
  252.         } else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' '))
  253.             return(0);
  254.         else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i);
  255.         You("don't know that spell.");
  256.         }
  257.     }
  258. }
  259.  
  260. int
  261. docast()
  262. {
  263.     register int     spell;
  264.  
  265.     spell = getspell();
  266.     if (!spell) return(0);
  267.  
  268.     return(spelleffects(spell,FALSE));
  269. }
  270.  
  271. int
  272. spelleffects(spell,atme)
  273. register int spell;
  274. boolean atme;
  275. {
  276.     register int energy, damage;
  277. #ifdef HARD
  278.     boolean confused = (Confusion != 0);
  279. #endif
  280.     struct obj *pseudo;
  281.  
  282. #ifdef HARD
  283.     /* note that trying to cast it decrements the # of uses,    */
  284.     /* even if the mage does not have enough food/energy to use */
  285.     /* the spell */
  286.     switch (spelluses(spell)) {
  287.         case 0:
  288.             pline ("That spell is too hard to recall at the moment.");
  289.             return(0);
  290.         case 1:
  291.             pline ("You can barely remember the runes of this spell.");
  292.             break;
  293.         case 2:
  294.             pline ("This spell is starting to be over-used.");
  295.             break;
  296.         default:
  297.             break;
  298.     }
  299.     decrnuses(spell);
  300. #endif
  301.     energy = spellev(spell);
  302.     if (u.uhave_amulet) {
  303.         You("feel the amulet draining your energy away.");
  304.         energy *= rnd(6);
  305.     }
  306.     if(energy > u.uen)  {
  307.         You("don't have enough energy to cast that spell.");
  308.         return(0);
  309.     } else    if ((u.uhunger <= 100 && spell != SPE_DETECT_FOOD) ||
  310.                         (ACURR(A_STR) < 6))  {
  311.         You("lack the strength for that spell.");
  312.         return(0);
  313.     } else    {
  314.         if (spell != SPE_DETECT_FOOD)
  315.             morehungry(energy * 10);
  316.         u.uen -= energy;
  317.     }
  318.     flags.botl = 1;
  319.  
  320. #ifdef HARD
  321.     if (confused ||
  322.         ((int)(ACURR(A_INT) + Luck) - 3 * spellev(spell)) < 0) {
  323.  
  324.         if (Hallucination)
  325.             pline("Far out... a light show!");
  326.         else    pline("The air around you crackles as you goof up.");
  327.         return(0);
  328.     }
  329. #endif
  330.  
  331. /*    pseudo is a temporary "false" object containing the spell stats. */
  332.     pseudo = mksobj(spellid(spell),FALSE);
  333.     pseudo->blessed = pseudo->cursed = 0;
  334.     pseudo->quan = 20;            /* do not let useup get it */
  335.     switch(pseudo->otyp)  {
  336.  
  337. /* These spells are all duplicates of wand effects */
  338.     case SPE_FORCE_BOLT:
  339.     case SPE_SLEEP:
  340.     case SPE_MAGIC_MISSILE:
  341.     case SPE_KNOCK:
  342.     case SPE_SLOW_MONSTER:
  343.     case SPE_WIZARD_LOCK:
  344.     case SPE_FIREBALL:
  345.     case SPE_CONE_OF_COLD:
  346.     case SPE_DIG:
  347.     case SPE_TURN_UNDEAD:
  348.     case SPE_POLYMORPH:
  349.     case SPE_TELEPORT_AWAY:
  350.     case SPE_CANCELLATION:
  351.     case SPE_FINGER_OF_DEATH:
  352.     case SPE_LIGHT:
  353.     case SPE_DETECT_UNSEEN:
  354. #ifdef MACOS
  355.         if (pseudo->otyp == SPE_DIG)
  356.         {
  357.             segments |= SEG_SPELL;
  358.         }
  359. #endif
  360.         if (!(objects[pseudo->otyp].bits & NODIR)) {
  361.             if (atme) u.dx = u.dy = u.dz = 0;
  362.             else (void) getdir(1);
  363.             if(!u.dx && !u.dy && !u.dz) {
  364.                 if((damage = zapyourself(pseudo)))
  365.                 losehp(damage, 
  366.         self_pronoun("zapped %sself with a spell", "him"),
  367.                     NO_KILLER_PREFIX);
  368.             } else    weffects(pseudo);
  369.         } else weffects(pseudo);
  370.         break;
  371. /* These are all duplicates of scroll effects */
  372.     case SPE_CONFUSE_MONSTER:
  373.     case SPE_DETECT_FOOD:
  374.     case SPE_CAUSE_FEAR:
  375.     case SPE_CHARM_MONSTER:
  376.     case SPE_REMOVE_CURSE:
  377.     case SPE_MAGIC_MAPPING:
  378.     case SPE_CREATE_MONSTER:
  379.     case SPE_IDENTIFY:
  380.     case SPE_GENOCIDE:
  381.         (void) seffects(pseudo);
  382.         break;
  383.     case SPE_HASTE_SELF:
  384.     case SPE_DETECT_TREASURE:
  385.     case SPE_DETECT_MONSTERS:
  386.     case SPE_LEVITATION:
  387.     case SPE_RESTORE_ABILITY:
  388.     case SPE_INVISIBILITY:
  389.         (void) peffects(pseudo);
  390.         break;
  391.     case SPE_HEALING:
  392.         You("feel a bit better.");
  393.         healup(rnd(8), 0, 0, 0);
  394.         break;
  395.     case SPE_CURE_BLINDNESS:
  396.         healup(0, 0, 0, 1);
  397.         break;
  398.     case SPE_CURE_SICKNESS:
  399.         if (Sick) You("are no longer ill.");
  400.         healup(0, 0, 1, 0);
  401.         break;
  402.     case SPE_EXTRA_HEALING:
  403.         You("feel a fair bit better.");
  404.         healup(d(2,8), 1, 0, 0);
  405.         break;
  406.     case SPE_CREATE_FAMILIAR:
  407.         make_familiar((struct obj *)0);
  408.         break;
  409.     case SPE_CLAIRVOYANCE:
  410.         do_vicinity_map();
  411.         break;
  412.     default:
  413.         impossible("Unknown spell %d attempted.", spell);
  414.         obfree(pseudo, (struct obj *)0);
  415.         return(0);
  416.     }
  417.     obfree(pseudo, (struct obj *)0);    /* now, get rid of it */
  418.     return(1);
  419. }
  420.  
  421. void
  422. losespells() {
  423.     register boolean confused = (Confusion != 0);
  424.     register int     n, nzap, i;
  425.  
  426.     book = 0;
  427.     for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
  428.     if (!n) return;
  429.     if (n < MAXSPELL) {
  430.         nzap = rnd(n);
  431.         if (nzap < n) nzap += confused;
  432.         for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL;
  433.     } else impossible("Too many spells memorized!");
  434.     return;
  435. }
  436.  
  437. static char
  438. spellet(spl)
  439. int spl;
  440. {
  441.     return (spl < 27) ? ('a' + spl - 1) : ('A' + spl - 27);
  442. }
  443.  
  444. int
  445. dovspell() {
  446.  
  447.     register int maxs, i;
  448.     char     buf[BUFSZ], any[BUFSZ];
  449.  
  450.     if (spl_book[0].sp_id == NO_SPELL)  {
  451.  
  452.         You("don't know any spells right now.");
  453.         return 0;
  454.     }
  455.  
  456.     for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
  457.     if (maxs >= MAXSPELL)  {
  458.  
  459.         impossible("Too many spells memorized.");
  460.         return 0;
  461.     }
  462.     morc = 0;        /* just to be sure */
  463.     cornline(0, "Currently known spells:");
  464.  
  465.     for(i = 1; i <= maxs; i++) {
  466.  
  467. #ifdef HARD
  468.         Sprintf(buf, "%c %c %s (%d)",
  469.             spellet(i), (spelluses(i)) ? '-' : '*',
  470.             spellname(i), spellev(i));
  471. #else
  472.         Sprintf(buf, "%c %s (%d)",
  473.             spellet(i),
  474.             spellname(i), spellev(i));
  475. #endif
  476.         cornline(1, buf);
  477.         any[i-1] = spellet(i);
  478.       }
  479.     any[i-1] = 0;
  480.     cornline(2, any);
  481.  
  482.     return 0;
  483. }
  484.  
  485.  
  486. #endif /* SPELLS /**/
  487.